package com.szsky.sky.config.Fileter;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.szsky.sky.utils.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@WebFilter(filterName = "appUrlFilter", urlPatterns = "/*")
public class AppUrlFilter implements Filter {

    private static final long FIVE_MINUTES_IN_MILLIS = TimeUnit.MINUTES.toMillis(5);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化代码
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        // 打印请求信息示例
        String params = httpRequest.getParameter("params");
        String requestURI = httpRequest.getRequestURI();
//        Map<String, String[]> parameterMap = new HashMap<>();
        if (requestURI.contains("/app/getMapKey")) {
            chain.doFilter(request, response);
            return;
        }
        if (requestURI.contains("/app/getVersion")) {
            String timestampStr = httpRequest.getParameter("timestamp");
            String[] timestamp = new String[1];
            timestamp[0] = timestampStr;
            Map<String, String[]> parameterMap = new HashMap<>();
            parameterMap.put("timestamp", timestamp);
            if (validateTimestamp(response, parameterMap, timestamp)) return;
//            HttpServletRequest wrappedRequest = requestDecode(response, httpRequest, params);
//            if (wrappedRequest == null) return;
            chain.doFilter(request, response);
            return;
        }
        if (requestURI.contains("/app/")) {
            if (StringUtils.isNotBlank(params)) {
                HttpServletRequest wrappedRequest = requestDecode(response, httpRequest, params);
                if (wrappedRequest == null) return;

                // 创建可重复读取的响应包装器
                BufferedServletResponseWrapper responseWrapper =
                        new BufferedServletResponseWrapper((HttpServletResponse) response);
                chain.doFilter(wrappedRequest, responseWrapper);

                responseEncode(response, responseWrapper);

                return;
            }
        }
        // 继续处理请求
        chain.doFilter(request, response);
    }

    private HttpServletRequest requestDecode(ServletResponse response, HttpServletRequest httpRequest, String params) throws IOException {
        Map<String, String[]> parameterMap;
        try {
            String decryptParams = AESUtil.decrypt(params);
            String decodeParams = Base64.decodeStr(decryptParams);

            // 解析解密后的参数
            parameterMap = parseParameters(decodeParams);
            String[] timestamp = parameterMap.get("timestamp");
            if (validateTimestamp(response, parameterMap, timestamp)) return null;
        } catch (Exception e) {
            // 解密失败，记录日志或返回错误
            log.error("解密失败:{}", e);
//            response.setContentType("text/plain");
//            response.getWriter().write("Invalid parameters");
            response.setContentType("application/json;charset=UTF-8");
            Map<String, Object> encryptedResponse = getEncryptedResponse(500, "系统异常", false);
            response.getWriter().write(JSON.toJSONString(encryptedResponse));
            return null;
        }

        // 包装请求，替换原始参数
        HttpServletRequest wrappedRequest = new CustomHttpServletRequestWrapper(httpRequest, parameterMap);
        return wrappedRequest;
    }

    private static boolean validateTimestamp(ServletResponse response, Map<String, String[]> parameterMap, String[] timestamp) throws IOException {
        if (timestamp == null || timestamp.length == 0 || StringUtils.isBlank(timestamp[0])) {
            response.setContentType("application/json;charset=UTF-8");
            PrintWriter out = response.getWriter();

            Map<String, Object> encryptedResponse = getEncryptedResponse(400, "请求时间戳缺失或已过期", false);
            out.print(JSON.toJSONString(encryptedResponse));
            out.flush();
            return true;
        }

        // 获取当前系统时间戳(毫秒)
        long currentTimestamp = System.currentTimeMillis();
        // 计算时间差(当前时间 - 前端时间)
        long timeDifference = currentTimestamp - Convert.toLong(timestamp[0]);

        // 如果时间差大于5分钟(300000毫秒)，则认为无效
        if (!parameterMap.containsKey("timestamp") || timeDifference > FIVE_MINUTES_IN_MILLIS) {
            response.setContentType("application/json;charset=UTF-8");
            // 返回包含错误信息的JSON格式数据
            PrintWriter out = response.getWriter();
            Map<String, Object> encryptedResponse = getEncryptedResponse(400, "请求时间戳缺失或已过期", false);
            out.print(JSON.toJSONString(encryptedResponse));
            out.flush();
            return true;
        }
        return false;
    }

    private void responseEncode(ServletResponse response, BufferedServletResponseWrapper responseWrapper) throws IOException {
        try {

            // 获取原始响应数据
            byte[] originalData = responseWrapper.getContentAsByteArray();
            String originalContent = new String(originalData, StandardCharsets.UTF_8);

            // 加密处理
            String encryptedContent = encryptResponse(originalContent);

            // 设置加密后的内容作为响应
            byte[] encryptedData = encryptedContent.getBytes(StandardCharsets.UTF_8);
            response.setContentLength(encryptedData.length);

            // 输出加密后的内容
            try (OutputStream out = response.getOutputStream()) {
                out.write(encryptedData);
                out.flush();
            }
        } catch (Exception e) {
            log.error("加密响应数据失败：{}", e);
            // 加密失败时返回错误信息
            response.setContentType("application/json;charset=UTF-8");
            PrintWriter out = response.getWriter();

            Map<String, Object> encryptedResponse = getEncryptedResponse(500, "failed", false);
            out.print(JSON.toJSONString(encryptedResponse));
            out.flush();
        }
    }

    // 解析参数字符串为Map
    private Map<String, String[]> parseParameters(String params) {
        Map<String, String[]> parameterMap = new HashMap<>();
        String[] paramPairs = params.split("&");

        for (String pair : paramPairs) {
            String[] keyValue = pair.split("=", 2);
            if (keyValue.length == 2) {
                parameterMap.put(keyValue[0], new String[]{keyValue[1]});
            }
        }

        return parameterMap;
    }

    @Override
    public void destroy() {
        // 销毁资源
    }

    /**
     * 请求包装类，用于替换请求参数
     */
    private static class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
        private final Map<String, String[]> customParameterMap;

        public CustomHttpServletRequestWrapper(HttpServletRequest request, Map<String, String[]> parameterMap) {
            super(request);
            this.customParameterMap = parameterMap;
        }

        @Override
        public String getParameter(String name) {
            String[] values = customParameterMap.get(name);
            return values != null && values.length > 0 ? values[0] : null;
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            return customParameterMap;
        }

        @Override
        public Enumeration<String> getParameterNames() {
            return Collections.enumeration(customParameterMap.keySet());
        }

        @Override
        public String[] getParameterValues(String name) {
            return customParameterMap.get(name);
        }
    }

    /**
     * 用于捕获响应内容的包装器
     */
    private static class BufferedServletResponseWrapper extends HttpServletResponseWrapper {
        private final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        private final PrintWriter writer;

        public BufferedServletResponseWrapper(HttpServletResponse response) {
            super(response);
            writer = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8));
        }

        @Override
        public ServletOutputStream getOutputStream() {
            return new ServletOutputStream() {
                @Override
                public boolean isReady() {
                    return true;
                }

                @Override
                public void setWriteListener(WriteListener listener) {
                    // 实现必要的方法
                }

                @Override
                public void write(int b) {
                    byteArrayOutputStream.write(b);
                }
            };
        }

        @Override
        public PrintWriter getWriter() {
            return writer;
        }

        public byte[] getContentAsByteArray() {
            writer.flush();
            return byteArrayOutputStream.toByteArray();
        }
    }

    /**
     * 对响应内容进行加密处理
     *
     * @param content 原始响应内容
     * @return 加密后的响应内容
     */
    private String encryptResponse(String content) {
        try {
            if (StringUtils.isBlank(content)) {
                Map<String, Object> encryptedResponse = getEncryptedResponse(500, "failed", false);
                return JSON.toJSONString(encryptedResponse);
            }
            // 将响应内容转换为JSON对象（根据实际情况调整）
            JSONObject jsonObject = JSON.parseObject(content);

            // 将JSON对象转换为Base64编码的字符串
            String base64Data = java.util.Base64.getEncoder().encodeToString(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8));

            // 使用AES加密Base64数据
            String encryptedData = AESUtil.encrypt(base64Data);

            // 构建加密后的响应结构
            Map<String, Object> encryptedResponse = getEncryptedResponse(200, "success", true);
            encryptedResponse.put("data", encryptedData);
            encryptedResponse.put("data2", content);

            // 返回加密后的JSON响应
            return JSON.toJSONString(encryptedResponse);
        } catch (Exception e) {
            log.error("加密响应内容失败: {}", content, e);
            // 加密失败时返回原始内容
            Map<String, Object> encryptedResponse = getEncryptedResponse(500, "failed", false);
            return JSON.toJSONString(encryptedResponse);

        }
    }

    private static Map<String, Object> getEncryptedResponse(int value, String failed, boolean value1) {
        Map<String, Object> encryptedResponse = new HashMap<>();
        encryptedResponse.put("code", value);
        encryptedResponse.put("message", failed);
        encryptedResponse.put("encryptFlag", value1);
        return encryptedResponse;
    }
}
